from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime, timedelta
import hashlib
import hmac
import json
import secrets
import string
from functools import wraps

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///license.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'your-secret-key-here'  # 与客户端保持一致

db = SQLAlchemy(app)

# 数据库模型
class License(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    license_key = db.Column(db.String(64), unique=True, nullable=False)
    user_name = db.Column(db.String(100), nullable=False)
    user_email = db.Column(db.String(100), nullable=False)
    machine_id = db.Column(db.String(32), nullable=True)  # 绑定的机器ID
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    expire_at = db.Column(db.DateTime, nullable=False)
    is_active = db.Column(db.Boolean, default=True)
    max_activations = db.Column(db.Integer, default=1)  # 最大激活次数
    current_activations = db.Column(db.Integer, default=0)  # 当前激活次数
    last_verify = db.Column(db.DateTime, nullable=True)
    
class LicenseLog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    license_key = db.Column(db.String(64), nullable=False)
    action = db.Column(db.String(50), nullable=False)  # verify, activate, deactivate
    machine_id = db.Column(db.String(32), nullable=True)
    ip_address = db.Column(db.String(45), nullable=True)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
    result = db.Column(db.String(20), nullable=False)  # success, failed
    message = db.Column(db.Text, nullable=True)

# 创建数据库表
with app.app_context():
    db.create_all()

def verify_signature(func):
    """验证请求签名"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            data = request.get_json()
            if not data:
                return jsonify({'valid': False, 'message': '无效的请求数据'}), 400
            
            signature = data.pop('signature', None)
            if not signature:
                return jsonify({'valid': False, 'message': '缺少签名'}), 400
            
            # 验证签名
            expected_signature = hmac.new(
                app.config['SECRET_KEY'].encode(),
                json.dumps(data, sort_keys=True).encode(),
                hashlib.sha256
            ).hexdigest()
            
            if not hmac.compare_digest(signature, expected_signature):
                return jsonify({'valid': False, 'message': '签名验证失败'}), 401
            
            return func(*args, **kwargs)
        except Exception as e:
            return jsonify({'valid': False, 'message': f'验证错误: {str(e)}'}), 500
    return wrapper

def generate_license_key():
    """生成license key"""
    # 生成32位随机字符串
    chars = string.ascii_uppercase + string.digits
    key = ''.join(secrets.choice(chars) for _ in range(32))
    # 格式化为 XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX
    formatted_key = '-'.join([key[i:i+4] for i in range(0, len(key), 4)])
    return formatted_key

@app.route('/api/license/verify', methods=['POST'])
@verify_signature
def verify_license():
    """验证license"""
    try:
        data = request.get_json()
        license_key = data.get('license_key')
        machine_id = data.get('machine_id')
        client_ip = request.remote_addr
        
        if not license_key or not machine_id:
            return jsonify({
                'valid': False,
                'message': '缺少必要参数'
            }), 400
        
        # 查找license
        license_obj = License.query.filter_by(license_key=license_key).first()
        
        if not license_obj:
            log_license_action(license_key, 'verify', machine_id, client_ip, 'failed', 'License不存在')
            return jsonify({
                'valid': False,
                'message': 'License Key无效'
            })
        
        # 检查是否激活
        if not license_obj.is_active:
            log_license_action(license_key, 'verify', machine_id, client_ip, 'failed', 'License已被禁用')
            return jsonify({
                'valid': False,
                'message': 'License已被禁用'
            })
        
        # 检查是否过期
        if datetime.utcnow() > license_obj.expire_at:
            log_license_action(license_key, 'verify', machine_id, client_ip, 'failed', 'License已过期')
            return jsonify({
                'valid': False,
                'message': 'License已过期，请联系客服续费'
            })
        
        # 检查机器绑定
        if license_obj.machine_id is None:
            # 首次激活，绑定机器
            if license_obj.current_activations >= license_obj.max_activations:
                log_license_action(license_key, 'verify', machine_id, client_ip, 'failed', '超过最大激活次数')
                return jsonify({
                    'valid': False,
                    'message': '该License已达到最大激活次数限制'
                })
            
            license_obj.machine_id = machine_id
            license_obj.current_activations += 1
            license_obj.last_verify = datetime.utcnow()
            db.session.commit()
            
            log_license_action(license_key, 'activate', machine_id, client_ip, 'success', '首次激活成功')
            
        elif license_obj.machine_id != machine_id:
            log_license_action(license_key, 'verify', machine_id, client_ip, 'failed', '机器ID不匹配')
            return jsonify({
                'valid': False,
                'message': 'License已绑定其他设备，如需更换设备请联系客服'
            })
        
        # 更新最后验证时间
        license_obj.last_verify = datetime.utcnow()
        db.session.commit()
        
        log_license_action(license_key, 'verify', machine_id, client_ip, 'success', '验证成功')
        
        return jsonify({
            'valid': True,
            'message': 'License验证成功',
            'expire_time': license_obj.expire_at.isoformat(),
            'user_info': {
                'name': license_obj.user_name,
                'email': license_obj.user_email
            }
        })
        
    except Exception as e:
        return jsonify({
            'valid': False,
            'message': f'服务器错误: {str(e)}'
        }), 500

@app.route('/api/license/create', methods=['POST'])
def create_license():
    """创建新的license（管理员接口）"""
    try:
        data = request.get_json()
        
        # 简单的管理员验证（实际应用中应该使用更安全的认证）
        admin_key = data.get('admin_key')
        if admin_key != 'your-admin-secret-key':  # 替换为您的管理员密钥
            return jsonify({'success': False, 'message': '无权限'}), 403
        
        user_name = data.get('user_name')
        user_email = data.get('user_email')
        days = data.get('days', 365)  # 默认1年
        max_activations = data.get('max_activations', 1)
        
        if not user_name or not user_email:
            return jsonify({
                'success': False,
                'message': '缺少用户信息'
            }), 400
        
        # 生成license key
        license_key = generate_license_key()
        
        # 确保key唯一
        while License.query.filter_by(license_key=license_key).first():
            license_key = generate_license_key()
        
        # 创建license记录
        expire_at = datetime.utcnow() + timedelta(days=days)
        
        new_license = License(
            license_key=license_key,
            user_name=user_name,
            user_email=user_email,
            expire_at=expire_at,
            max_activations=max_activations
        )
        
        db.session.add(new_license)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'license_key': license_key,
            'expire_at': expire_at.isoformat(),
            'message': 'License创建成功'
        })
        
    except Exception as e:
        return jsonify({
            'success': False,
            'message': f'创建失败: {str(e)}'
        }), 500

@app.route('/api/license/list', methods=['POST'])
def list_licenses():
    """获取license列表（管理员接口）"""
    try:
        data = request.get_json()
        
        # 管理员验证
        admin_key = data.get('admin_key')
        if admin_key != 'your-admin-secret-key':
            return jsonify({'success': False, 'message': '无权限'}), 403
        
        page = data.get('page', 1)
        per_page = data.get('per_page', 20)
        
        licenses = License.query.paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        license_list = []
        for license_obj in licenses.items:
            license_list.append({
                'id': license_obj.id,
                'license_key': license_obj.license_key,
                'user_name': license_obj.user_name,
                'user_email': license_obj.user_email,
                'machine_id': license_obj.machine_id,
                'created_at': license_obj.created_at.isoformat(),
                'expire_at': license_obj.expire_at.isoformat(),
                'is_active': license_obj.is_active,
                'current_activations': license_obj.current_activations,
                'max_activations': license_obj.max_activations,
                'last_verify': license_obj.last_verify.isoformat() if license_obj.last_verify else None
            })
        
        return jsonify({
            'success': True,
            'licenses': license_list,
            'total': licenses.total,
            'pages': licenses.pages,
            'current_page': page
        })
        
    except Exception as e:
        return jsonify({
            'success': False,
            'message': f'获取失败: {str(e)}'
        }), 500

@app.route('/api/license/deactivate', methods=['POST'])
def deactivate_license():
    """禁用license（管理员接口）"""
    try:
        data = request.get_json()
        
        # 管理员验证
        admin_key = data.get('admin_key')
        if admin_key != 'your-admin-secret-key':
            return jsonify({'success': False, 'message': '无权限'}), 403
        
        license_key = data.get('license_key')
        if not license_key:
            return jsonify({'success': False, 'message': '缺少license_key'}), 400
        
        license_obj = License.query.filter_by(license_key=license_key).first()
        if not license_obj:
            return jsonify({'success': False, 'message': 'License不存在'}), 404
        
        license_obj.is_active = False
        db.session.commit()
        
        log_license_action(license_key, 'deactivate', None, request.remote_addr, 'success', '管理员禁用')
        
        return jsonify({
            'success': True,
            'message': 'License已禁用'
        })
        
    except Exception as e:
        return jsonify({
            'success': False,
            'message': f'禁用失败: {str(e)}'
        }), 500

def log_license_action(license_key, action, machine_id, ip_address, result, message):
    """记录license操作日志"""
    try:
        log_entry = LicenseLog(
            license_key=license_key,
            action=action,
            machine_id=machine_id,
            ip_address=ip_address,
            result=result,
            message=message
        )
        db.session.add(log_entry)
        db.session.commit()
    except Exception as e:
        print(f"日志记录失败: {e}")

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)